import { _decorator, Component, Node, Vec3, Animation, tween, UITransform, Sprite, Color, find } from 'cc';
import { GameManager } from '../GameManager';
import { EventManager, GameEventType } from '../Core/EventManager';
import { DataManager, EnemyConfig } from '../Core/DataManager';
import { ObjectPool } from '../Core/ObjectPool';

const { ccclass, property } = _decorator;

// Enemy states
enum EnemyState {
    IDLE = 'idle',
    MOVE = 'move',
    ATTACK = 'attack',
    HIT = 'hit',
    DEATH = 'death'
}

@ccclass('EnemyController')
export class EnemyController extends Component {
    @property
    protected enemyId: string = "";
    
    @property
    protected health: number = 50;
    
    @property
    protected maxHealth: number = 50;
    
    @property
    protected damage: number = 10;
    
    @property
    protected moveSpeed: number = 100;
    
    @property
    protected attackRange: number = 1.5;
    
    @property
    protected attackSpeed: number = 1;
    
    @property(Node)
    protected healthBar: Node = null;
    
    @property(Node)
    protected healthBarBg: Node = null;
    
    @property(Animation)
    protected anim: Animation = null;
    
    protected _config: EnemyConfig = null;
    protected _target: Node = null;
    protected _currentState: EnemyState = EnemyState.IDLE;
    protected _attackTimer: number = 0;
    
    start() {
        // Load enemy configuration
        this._config = DataManager.instance.getEnemyConfig(this.enemyId);
        
        // Apply configuration values if available
        if (this._config) {
            this.health = this._config.health;
            this.maxHealth = this._config.health;
            this.damage = this._config.damage;
            this.moveSpeed = this._config.moveSpeed;
            this.attackRange = this._config.attackRange;
            this.attackSpeed = this._config.attackSpeed;
        }
        
        // Find player as target
        this._target = GameManager.instance.getPlayer();
        
        // Initialize health bar
        this.updateHealthBar();
    }
    
    update(deltaTime: number) {
        if (GameManager.instance.isGameOver) {
            return;
        }
        
        // Update attack timer
        this._attackTimer += deltaTime;
        
        // Update behavior based on state
        switch (this._currentState) {
            case EnemyState.IDLE:
                this.updateIdle(deltaTime);
                break;
                
            case EnemyState.MOVE:
                this.updateMovement(deltaTime);
                break;
                
            case EnemyState.ATTACK:
                this.updateAttack(deltaTime);
                break;
                
            case EnemyState.HIT:
                // Do nothing, waiting for hit animation to finish
                break;
                
            case EnemyState.DEATH:
                // Do nothing, waiting for death animation to finish
                break;
        }
        
        // Update animation
        this.updateAnimation();
    }
    
    protected updateIdle(deltaTime: number): void {
        // Transition to move state if player is found
        if (this._target) {
            this._currentState = EnemyState.MOVE;
        }
    }
    
    protected updateMovement(deltaTime: number): void {
        if (!this._target) {
            this._currentState = EnemyState.IDLE;
            return;
        }
        
        // Calculate distance to player
        const distanceToPlayer = Vec3.distance(this.node.position, this._target.position);
        
        // If in attack range, switch to attack state
        if (distanceToPlayer <= this.attackRange) {
            this._currentState = EnemyState.ATTACK;
            return;
        }
        
        // Move towards player
        const direction = new Vec3();
        Vec3.subtract(direction, this._target.position, this.node.position);
        direction.normalize();
        
        // Apply movement
        const movement = direction.multiplyScalar(this.moveSpeed * deltaTime);
        this.node.position = this.node.position.add(movement);
        
        // Update rotation to face player
        this.updateRotation(direction);
    }
    
    protected updateAttack(deltaTime: number): void {
        if (!this._target) {
            this._currentState = EnemyState.IDLE;
            return;
        }
        
        // Check if player is still in range
        const distanceToPlayer = Vec3.distance(this.node.position, this._target.position);
        if (distanceToPlayer > this.attackRange) {
            this._currentState = EnemyState.MOVE;
            return;
        }
        
        // Attack if timer is ready
        if (this._attackTimer >= 1 / this.attackSpeed) {
            this.attack();
            this._attackTimer = 0;
        }
    }
    
    protected attack(): void {
        // Apply damage to player
        EventManager.instance.emit(GameEventType.PLAYER_DAMAGE, this.damage);
    }
    
    protected updateRotation(direction: Vec3): void {
        // Calculate angle in degrees
        const angle = Math.atan2(direction.y, direction.x) * 180 / Math.PI;
        
        // Set rotation in Z axis
        this.node.angle = -angle;
    }
    
    protected updateAnimation(): void {
        if (this.anim) {
            const animName = this._currentState.toLowerCase();
            if (!this.anim.getState(animName).isPlaying) {
                this.anim.play(animName);
            }
        }
    }
    
    public takeDamage(damage: number): void {
        if (this._currentState === EnemyState.DEATH) return;
        
        this.health -= damage;
        
        // Update health bar
        this.updateHealthBar();
        
        // Play hit effect
        this.playHitEffect();
        
        // Check for death
        if (this.health <= 0) {
            this.health = 0;
            this.die();
        } else {
            // Just play hit animation
            this._currentState = EnemyState.HIT;
            
            // Return to previous state after hit animation
            setTimeout(() => {
                if (this._currentState === EnemyState.HIT) {
                    this._currentState = EnemyState.MOVE;
                }
            }, 300);
        }
    }
    
    protected updateHealthBar(): void {
        if (this.healthBar) {
            // Calculate health percentage
            const healthPercent = this.health / this.maxHealth;
            
            // Update health bar width
            const transform = this.healthBar.getComponent(UITransform);
            const bgTransform = this.healthBarBg.getComponent(UITransform);
            
            if (transform && bgTransform) {
                transform.width = bgTransform.width * healthPercent;
            }
        }
    }
    
    protected playHitEffect(): void {
        // Flash sprite
        const sprite = this.node.getComponent(Sprite);
        if (sprite) {
            const originalColor = sprite.color.clone();
            
            // Set to white for flash effect
            sprite.color = Color.WHITE;
            
            // Return to original color
            setTimeout(() => {
                sprite.color = originalColor;
            }, 100);
        }
    }
    
    protected die(): void {
        this._currentState = EnemyState.DEATH;
        
        // Play death animation
        if (this.anim) {
            this.anim.play('death');
            
            // Wait for animation to finish before removing
            const deathAnimState = this.anim.getState('death');
            const deathDuration = deathAnimState ? deathAnimState.duration : 1;
            
            setTimeout(() => {
                this.onDeathComplete();
            }, deathDuration * 1000);
        } else {
            // No animation, remove immediately
            this.onDeathComplete();
        }
    }
    
    protected onDeathComplete(): void {
        // Drop items
        this.dropItems();
        
        // Emit enemy death event
        EventManager.instance.emit(GameEventType.ENEMY_DEATH, {
            position: this.node.position,
            enemyId: this.enemyId
        });
        
        // Add score
        GameManager.instance.addScore(this._config ? this._config.health : 10);
        
        // Remove from scene
        this.node.destroy();
    }
    
    protected dropItems(): void {
        if (!this._config || !this._config.dropItems) return;
        
        // Process each drop item in the enemy config
        for (let i = 0; i < this._config.dropItems.length; i++) {
            const dropInfo = this._config.dropItems[i];
            
            // Check if item should drop based on chance
            if (Math.random() <= dropInfo.chance) {
                // Determine quantity if specified
                let quantity = 1;
                if (dropInfo.min !== undefined && dropInfo.max !== undefined) {
                    quantity = Math.floor(Math.random() * (dropInfo.max - dropInfo.min + 1)) + dropInfo.min;
                }
                
                // Create drop item(s)
                for (let j = 0; j < quantity; j++) {
                    this.createDropItem(dropInfo.type);
                }
            }
        }
    }
    
    protected createDropItem(itemType: string): void {
        // Get item prefab from pool or create new
        const itemPrefab = `Item_${itemType}`;
        let itemNode = ObjectPool.instance.getObject(itemPrefab, this.node.position);
        
        // If no pool available, create manually
        if (!itemNode) {
            // This is a fallback in case we don't have a pool for this item type
            const itemsNode = find('Items') || new Node('Items');
            if (itemsNode.parent === null) {
                this.node.scene.addChild(itemsNode);
            }
            
            itemNode = new Node(`Item_${itemType}`);
            itemsNode.addChild(itemNode);
            itemNode.position = this.node.position.clone();
            
            // Add necessary components
            // This is just a placeholder - actual implementation would add proper item component
            const itemScript = itemNode.addComponent('ItemController');
            if (itemScript) {
                // Initialize item
                // itemScript.initialize(itemType);
            }
        }
    }
} 